package com.csw.android.androidtest.module.thread;

import android.os.Handler;
import android.os.HandlerThread;
import android.view.View;

/**
 * 类似与android主线程循环执行任务的机制，android提供了HandlerThread类，提供循环执行任务模式的子线程，可以实现单线程顺序执行多任务
 */
public class HandlerThreadTest extends ThreadTest {

    private final MyHandlerThread handlerThread = new MyHandlerThread();

    @Override
    public void initListener() {
        super.initListener();
        run.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                logs = new StringBuffer();
                appendLog(null);
                for (int i = 1; i <= 10; i++) {
                    final int task = i;
                    //往子线程post任务，他会按照插入位置顺序执行,这里getLooper，若子线程还未start，则返回null导致handler内部获取消息队列空指针
                    //若线程已经start,但run还未执行，则getLooper时线程会阻塞至looper创建完毕后被唤醒，一般会很快唤醒，所以这里这么做并不会感觉到卡顿
                    new Handler(handlerThread.getLooper()).postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            appendLog(task + "");
                        }
                    }, 1000);
                }
            }
        });
    }

    private void appendLog(String taskName) {
        synchronized (this) {
            logs.append("runOn___>");
            logs.append(Thread.currentThread().getName());
            if (taskName != null) {
                logs.append(" task ");
                logs.append(taskName);
            }
            logs.append("\n");
            updateLog();
        }
    }

    @Override
    public void initData() {
        super.initData();
        //开启任务处理线程
        handlerThread.start();
    }

    @Override
    public void onDestroyView() {
        //强制退出，没执行完的任务不执行
        handlerThread.quit();
        //安全退出，执行完执行此方法之前提交的所有任务后再结束
        handlerThread.quitSafely();
        super.onDestroyView();
    }

    /**
     * HandlerThread线程开始执行时(run)会去创建looper(内部创建消息队列)，然后唤醒因为调用getLooper()而陷入阻塞的线程，
     * 然后再回调onLooperPrepared告知looper已经准备好了，最后通过looper.loop循环执行消息队列的任务。
     * <p>
     * 可以通过looper创建handler，handler将绑定该looper的消息队列，当通过handler post任务时，会插入到消息队列中等待线程执行
     */
    private static class MyHandlerThread extends HandlerThread {

        public MyHandlerThread() {
            super("thread 0");
        }

        @Override
        public void run() {
//            //测试若线程还未创建looper，是否会阻塞，证实是会的
//            try {
//                Thread.sleep(10*1000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
            super.run();
        }

        @Override
        protected void onLooperPrepared() {
            super.onLooperPrepared();
            //回调此方法时，looper已经创建并可用了，可以用于创建handler
        }
    }
}
